package com.yzjs.common.util;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;
import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
import net.coobird.thumbnailator.Thumbnails;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.multipart.MultipartFile;

/**
 * 获取图片尺寸和截图 工具类
 *
 * @author zhangxiaoyan
 */
public class ImageSizeUtil {

	private final static Logger logger = LoggerFactory.getLogger(ImageSizeUtil.class);

	/**
	 * 获取图片最长边长度
	 *
	 * @param params
	 * @return
	 */
	public static int getImageLengthOfSide(MultipartFile params) {
		int lengthSize = 0;
		// 获取图片格式
		String suffixName = ImageSizeUtil.getSuffixNameInfo(params);
		try {
			Iterator<ImageReader> readers = ImageIO.getImageReadersByFormatName(suffixName);
			ImageReader reader = readers.next();
			ImageInputStream iis = ImageIO.createImageInputStream(params.getInputStream());
			reader.setInput(iis, true);
			if (reader.getWidth(0) > reader.getHeight(0)) {
				lengthSize = reader.getWidth(0);
			} else {
				lengthSize = reader.getHeight(0);
			}
		} catch (IOException e) {
			e.printStackTrace();
		}

		return lengthSize;
	}

	/**
	 * 获取图片最长边长度
	 *
	 * @param params
	 * @return
	 */
	public static ImageReader getImage(MultipartFile params) {
		// 获取图片格式
		String suffixName = ImageSizeUtil.getSuffixNameInfo(params);
		try {
			Iterator<ImageReader> readers = ImageIO.getImageReadersByFormatName(suffixName);
			ImageReader reader = readers.next();
			ImageInputStream iis = ImageIO.createImageInputStream(params.getInputStream());
			reader.setInput(iis, true);
			return reader;
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 获取图片格式
	 *
	 * @param params
	 * @return
	 */
	public static String getSuffixNameInfo(MultipartFile params) {
		String result = "";
		// 图片后缀
		String suffixName = params.getOriginalFilename().substring(params.getOriginalFilename().lastIndexOf("."));
		if (suffixName.toLowerCase().indexOf("png") > 0) {
			result = "png";
		} else if (suffixName.toLowerCase().indexOf("jpg") > 0) {
			result = "jpg";
		} else if (suffixName.toLowerCase().indexOf("jpeg") > 0) {
			result = "jpeg";
		}

		return result;
	}

	/**
	 * 根据指定大小压缩图片
	 *
	 * @param imageBytes 源图片字节数组
	 * @param desFileSize 指定图片大小，单位kb
	 * @return 压缩质量后的图片字节数组
	 */
	public static byte[] compressPic(byte[] imageBytes, int width, int height) {
		long srcSize = imageBytes.length;
		try {
			ByteArrayInputStream inputStream = new ByteArrayInputStream(imageBytes);
			ByteArrayOutputStream outputStream = new ByteArrayOutputStream(imageBytes.length);
			Thumbnails.of(inputStream).size(width, height).toOutputStream(outputStream);
			imageBytes = outputStream.toByteArray();
			ImageSizeUtil.logger.info("【图片压缩】imageId={} | 图片原大小={}kb | 压缩后大小={}kb", "", srcSize / 1024,
					imageBytes.length / 1024);
		} catch (Exception e) {
			ImageSizeUtil.logger.error("【图片压缩】msg=图片压缩失败!", e);
		}
		return imageBytes;
	}

	/**
	 * 根据指定大小压缩图片
	 *
	 * @param imageBytes 源图片字节数组
	 * @param desFileSize 指定图片大小，单位kb
	 * @return 压缩质量后的图片字节数组
	 */
	public static byte[] compressPicForScale(byte[] imageBytes, long desFileSize) {
		if (imageBytes == null || imageBytes.length <= 0 || imageBytes.length < desFileSize * 1024) {
			return imageBytes;
		}
		long srcSize = imageBytes.length;
		double accuracy = ImageSizeUtil.getAccuracy(srcSize / 1024);
		// double accuracy = 0.85;
		try {
			while (imageBytes.length > desFileSize * 1024) {
				ByteArrayInputStream inputStream = new ByteArrayInputStream(imageBytes);
				ByteArrayOutputStream outputStream = new ByteArrayOutputStream(imageBytes.length);
				Thumbnails.of(inputStream).scale(accuracy).outputQuality(accuracy).toOutputStream(outputStream);
				imageBytes = outputStream.toByteArray();
			}
			ImageSizeUtil.logger.info("【图片压缩】imageId={} | 图片原大小={}kb | 压缩后大小={}kb", "", srcSize / 1024,
					imageBytes.length / 1024);
		} catch (Exception e) {
			ImageSizeUtil.logger.error("【图片压缩】msg=图片压缩失败!", e);
		}
		return imageBytes;
	}

	/**
	 * 自动调节精度(经验数值)
	 *
	 * @param size 源图片大小，单位kb
	 * @return 图片压缩质量比
	 */
	private static double getAccuracy(long size) {
		double accuracy;
		if (size < 900) {
			accuracy = 0.85;
		} else if (size < 2047) {
			// accuracy = 0.6;
			accuracy = 0.8;
		} else if (size < 3275) {
			// accuracy = 0.44;
			accuracy = 0.7;
		} else {
			accuracy = 0.4;
		}
		return accuracy;
	}

	/**
	 * 压缩图片
	 * maxLength 最大长度，等比压缩压缩后，长或宽最大长度不超过此长度
	 *
	 * @return
	 */
	public static InputStream compressInputStream(MultipartFile fileImg, int maxLength) {
		InputStream result = null;
		// 获取图片最长边
		int imageLengthSize = ImageSizeUtil.getImageLengthOfSide(fileImg);
		try {
			if (imageLengthSize <= maxLength) {
				return fileImg.getInputStream();
			}
			ImageReader getImage = ImageSizeUtil.getImage(fileImg);
			int sourceWidth = getImage.getWidth(0);
			int sourceHeight = getImage.getHeight(0);
			double rate = maxLength * 1.0 / imageLengthSize;
			int destWidth = new Double(sourceWidth * rate).intValue();
			int destHeight = new Double(sourceHeight * rate).intValue();
			InputStream inputStream = fileImg.getInputStream();
			byte[] imgData = ImageSizeUtil.compressPic(ImageSizeUtil.getByteArray(inputStream), destWidth, destHeight);
			return new ByteArrayInputStream(imgData);
		} catch (IOException e) {
			e.printStackTrace();
		}
		return result;
	}

	/**
	 * InputStream转换为byte[]
	 *
	 * @param inStream
	 * @return
	 * @throws IOException
	 */
	public static final byte[] getByteArray(InputStream inStream) throws IOException {
		ByteArrayOutputStream swapStream = new ByteArrayOutputStream();
		byte[] buff = new byte[100];
		int rc = 0;
		while ((rc = inStream.read(buff, 0, 100)) > 0) {
			swapStream.write(buff, 0, rc);
		}
		byte[] in2b = swapStream.toByteArray();
		return in2b;
	}

}